<!--
  扫描二维码/条形码（无法打开闪光灯）       zls  2022-08-01
      安卓手机：自带浏览器、百度、360手机极速浏览器、Edeg
      苹果手机：自带浏览器
  
  父组件调用子组件的 openScan(callback) 方法，用于打开扫描框并在回调函数中回去扫描结果

  Demo==>
      <template>
        <div class="home">
          <Button type="primary" size="small" @click="openScan">扫描二维码/条形码</Button>
          <div>扫描结果===={{ scanResult }}</div>
          <Scan ref="scanRef"></Scan>
        </div>
      </template>

      <script setup>
      import { ref } from 'vue'
      import { Button } from 'vant'
      import Scan from '@/components/Scan.vue'
      const scanRef = ref()
      const scanResult = ref('')
      function openScan() {
        scanRef.value.openScan(val => {
          scanResult.value = val
        })
      }
      </script>
-->
<template>
  <div class="scan-box" v-if="showScan">
    <!-- 扫码区域 -->
    <div class="QrCode">
      <video ref="video" height="100%" width="100%" id="video" autoplay></video>
    </div>
    <!-- 扫码样式一 -->
    <div class="Qr_scanner">
      <div class="box">
        <div class="line_row">
          <div class="line"></div>
        </div>
        <div class="angle"></div>
      </div>
      <div class="openTorch">
        <Button type="primary" size="small" @click="closeScan">关闭扫描框</Button>
      </div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, onUnmounted, reactive, ref } from 'vue'
import { Button, Notify } from 'vant'

import 'webrtc-adapter'
import { BrowserMultiFormatReader, ChecksumException } from '@zxing/library'
const showScan = ref(false)
const codeReader = reactive({ obj: {} })

onMounted(() => {
  codeReader.obj = new BrowserMultiFormatReader()
})

onUnmounted(() => {
  codeReader.obj && codeReader.obj.reset()
  codeReader.obj = null
})

function openScan(callback) {
  showScan.value = true
  codeReader.obj
    .getVideoInputDevices()
    .then(videoInputDevices => {
      if (videoInputDevices?.length > 1) {
        videoInputDevices.reverse()
      }
      decodeFromInputVideoFunc(videoInputDevices[0].deviceId, callback)
    })
    .catch(err => {
      console.error(err)
    })
}
function decodeFromInputVideoFunc(firstDeviceId, callback) {
  codeReader.obj.decodeFromInputVideoDeviceContinuously(firstDeviceId, 'video', (result, err) => {
    if (result) {
      Notify({ type: 'success', message: '扫描成功' })
      callback(result)
      closeScan()
    }
    if (err) {
      if (err instanceof ChecksumException) {
        Notify({ type: 'danger', message: '扫描失败' })
        callback('')
        closeScan()
      }
    }
  })
}
function closeScan() {
  codeReader.obj && codeReader.obj.reset()
  showScan.value = false
}

defineExpose({ openScan })
</script>

<style lang="scss" scoped>
.scan {
  height: calc(100% - 50px);
  padding: 15px;
  .popup-main {
    margin-top: 40px;
    height: calc(100% - 40px);
    padding: 0 15px;
    overflow-y: auto;
  }
}

.scan-box {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 999;
}
.QrCode {
  width: 100%;
  height: 100%;
  position: relative;
  #video {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}
.Qr_scanner {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.4);
  .box {
    width: 75vw;
    height: 75vw;
    max-height: 75vh;
    max-width: 75vh;
    position: relative;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    border: 1px solid rgb(43, 113, 254);
    .line_row {
      width: 100%;
      overflow: hidden;
      background-image: linear-gradient(
          0deg,
          transparent 24%,
          rgba(136, 176, 255, 0.1) 25%,
          rgba(136, 176, 255, 0.1) 26%,
          transparent 27%,
          transparent 74%,
          rgba(136, 176, 255, 0.1) 75%,
          rgba(136, 176, 255, 0.1) 76%,
          transparent 77%,
          transparent
        ),
        linear-gradient(
          90deg,
          transparent 24%,
          rgba(136, 176, 255, 0.1) 25%,
          rgba(136, 176, 255, 0.1) 26%,
          transparent 27%,
          transparent 74%,
          rgba(136, 176, 255, 0.1) 75%,
          rgba(136, 176, 255, 0.1) 76%,
          transparent 77%,
          transparent
        );
      background-size: 3rem 3rem;
      background-position: -1rem -1rem;
      animation: Heightchange 2s infinite;
      animation-timing-function: cubic-bezier(0.53, 0, 0.43, 0.99);
      animation-delay: 1.4s;
      border-bottom: 1px solid rgba(136, 176, 255, 0.1);
      display: flex;
      justify-content: center;
      align-items: flex-end;
    }
  }
  .line {
    width: 100%;
    height: 3px;
    background: #2b71fe;
    // opacity: 0.58;
    filter: blur(4px);
  }
  .box:after,
  .box:before,
  .angle:after,
  .angle:before {
    content: '';
    display: block;
    position: absolute;
    width: 78px;
    height: 78px;
    border: 0.3rem solid transparent;
  }
  .box:after,
  .box:before {
    top: -7px;
    border-top-color: #2b71fe;
  }
  .angle:after,
  .angle:before {
    bottom: -7px;
    border-bottom-color: #2b71fe;
  }
  .box:before,
  .angle:before {
    left: -7px;
    border-left-color: #2b71fe;
  }
  .box:after,
  .angle:after {
    right: -7px;
    border-right-color: #2b71fe;
  }
  @keyframes radar-beam {
    0% {
      transform: translateY(-100%);
    }
    100% {
      transform: translateY(0);
    }
  }
  @keyframes Heightchange {
    0% {
      height: 0;
    }
    100% {
      height: 100%;
    }
  }
}
.openTorch {
  position: relative;
  left: 50%;
  top: 45%;
  transform: translate(-50%, -50%);
  @include flex();
  .van-button {
    margin: 0 5px;
  }
}
</style>
